#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
策略基础类
定义策略的基本接口和通用功能
"""

from abc import ABC, abstractmethod
from typing import Dict, Any, Optional, List
from datetime import datetime
from enum import Enum

from config.config_manager import get_config
from utils.logger import get_logger, trade_log, position_log
from utils.exceptions import StrategyError, StrategyInitializationError
from core.base_classes import BaseStrategy


class SignalType(Enum):
    """信号类型"""
    BUY = "BUY"
    SELL = "SELL"
    HOLD = "HOLD"


class OrderType(Enum):
    """订单类型"""
    MARKET = "MARKET"  # 市价单
    LIMIT = "LIMIT"    # 限价单
    STOP = "STOP"      # 止损单


class StrategyStatus(Enum):
    """策略状态"""
    INITIALIZING = "INITIALIZING"
    RUNNING = "RUNNING"
    PAUSED = "PAUSED"
    STOPPED = "STOPPED"
    ERROR = "ERROR"


class BaseStrategy(BaseStrategy):
    """策略基础类"""

    def __init__(self, symbol: str, config: Optional[Dict[str, Any]] = None):
        if config is None:
            config = get_config()
            config = config.strategy.__dict__ if hasattr(config, 'strategy') else {}

        super().__init__(symbol, config)

        # 策略配置
        self.strategy_name = config.get('name', 'base_strategy')
        self.max_position = config.get('max_position', 10)
        self.min_position = config.get('min_position', 1)

        # 策略状态
        self.status = StrategyStatus.INITIALIZING
        self.start_time = None
        self.last_update_time = None

        # 信号历史
        self.signal_history = []

        self.logger.info(f"策略 {self.strategy_name} 初始化: {symbol}")

    async def initialize(self):
        """初始化策略"""
        try:
            self.logger.info(f"开始初始化策略: {self.strategy_name}")

            # 子类特定的初始化
            await self._initialize_strategy()

            self.status = StrategyStatus.RUNNING
            self.start_time = datetime.now()

            self.logger.info(f"策略 {self.strategy_name} 初始化完成")

        except Exception as e:
            self.status = StrategyStatus.ERROR
            self.logger.error(f"策略 {self.strategy_name} 初始化失败: {e}")
            raise StrategyInitializationError(f"策略初始化失败: {e}")

    @abstractmethod
    async def _initialize_strategy(self):
        """子类特定的初始化逻辑"""
        pass

    @abstractmethod
    async def on_quote_update(self, quote: Dict[str, Any]):
        """行情更新回调"""
        pass

    @abstractmethod
    async def on_kline_update(self, kline: Dict[str, Any]):
        """K线更新回调"""
        pass

    @abstractmethod
    async def generate_signal(self) -> Optional[SignalType]:
        """生成交易信号"""
        pass

    @abstractmethod
    async def calculate_position_size(self) -> int:
        """计算仓位大小"""
        pass

    async def execute_signal(self, signal: SignalType) -> Optional[Dict[str, Any]]:
        """执行交易信号"""
        try:
            if signal == SignalType.HOLD:
                return None

            # 计算仓位大小
            position_size = await self.calculate_position_size()
            if position_size <= 0:
                self.logger.warning(f"计算的仓位大小无效: {position_size}")
                return None

            # 确定交易方向
            if signal == SignalType.BUY:
                direction = "BUY"
                target_position = position_size
            else:  # SELL
                direction = "SELL"
                target_position = -position_size

            # 检查是否需要调整仓位
            if self.position == target_position:
                self.logger.debug("当前仓位已是目标仓位，无需调整")
                return None

            # 执行交易
            trade_result = await self._execute_trade(direction, abs(target_position - self.position))

            # 更新策略状态
            self.position = target_position
            self.last_update_time = datetime.now()

            # 记录信号历史
            self.signal_history.append({
                'timestamp': datetime.now(),
                'signal': signal.value,
                'position_before': self.position,
                'position_after': target_position,
                'trade_result': trade_result
            })

            # 限制信号历史长度
            if len(self.signal_history) > 1000:
                self.signal_history = self.signal_history[-500:]

            return trade_result

        except Exception as e:
            self.logger.error(f"执行信号失败 {signal}: {e}")
            return None

    @abstractmethod
    async def _execute_trade(self, direction: str, volume: int) -> Dict[str, Any]:
        """执行具体交易逻辑"""
        pass

    async def pause(self):
        """暂停策略"""
        self.status = StrategyStatus.PAUSED
        self.logger.info(f"策略 {self.strategy_name} 已暂停")

    async def resume(self):
        """恢复策略"""
        if self.status == StrategyStatus.PAUSED:
            self.status = StrategyStatus.RUNNING
            self.logger.info(f"策略 {self.strategy_name} 已恢复")

    async def stop(self):
        """停止策略"""
        self.status = StrategyStatus.STOPPED
        self.logger.info(f"策略 {self.strategy_name} 已停止")

    def is_running(self) -> bool:
        """检查策略是否正在运行"""
        return self.status == StrategyStatus.RUNNING

    def get_status_info(self) -> Dict[str, Any]:
        """获取策略状态信息"""
        return {
            'strategy_name': self.strategy_name,
            'symbol': self.symbol,
            'status': self.status.value,
            'position': self.position,
            'entry_price': self.entry_price,
            'start_time': self.start_time.isoformat() if self.start_time else None,
            'last_update_time': self.last_update_time.isoformat() if self.last_update_time else None,
            'total_trades': self.total_trades,
            'winning_trades': self.winning_trades,
            'total_pnl': self.total_pnl,
            'signal_history_count': len(self.signal_history)
        }

    def get_performance_metrics(self) -> Dict[str, Any]:
        """获取性能指标"""
        if self.total_trades == 0:
            return {
                'win_rate': 0.0,
                'avg_pnl': 0.0,
                'total_return': 0.0,
                'max_drawdown': 0.0
            }

        win_rate = self.winning_trades / self.total_trades

        # 计算最大回撤（简化版）
        cumulative_pnl = 0
        peak = 0
        max_drawdown = 0

        for trade in self.signal_history:
            if 'trade_result' in trade and trade['trade_result']:
                pnl = trade['trade_result'].get('pnl', 0)
                cumulative_pnl += pnl

                if cumulative_pnl > peak:
                    peak = cumulative_pnl
                elif peak > cumulative_pnl:
                    drawdown = peak - cumulative_pnl
                    if drawdown > max_drawdown:
                        max_drawdown = drawdown

        return {
            'win_rate': win_rate,
            'avg_pnl': self.total_pnl / self.total_trades,
            'total_return': self.total_pnl,
            'max_drawdown': max_drawdown
        }

    async def cleanup(self):
        """清理策略资源"""
        try:
            self.logger.info(f"清理策略 {self.strategy_name} 资源")
            # 子类特定的清理逻辑
            await self._cleanup_strategy()
        except Exception as e:
            self.logger.error(f"清理策略失败: {e}")

    async def _cleanup_strategy(self):
        """子类特定的清理逻辑"""
        pass


class StrategyManager:
    """策略管理器"""

    def __init__(self):
        self.logger = get_logger("StrategyManager")
        self.strategies = {}
        self.active_strategies = set()

    async def register_strategy(self, strategy: BaseStrategy):
        """注册策略"""
        strategy_name = strategy.strategy_name
        symbol = strategy.symbol

        key = f"{strategy_name}_{symbol}"
        self.strategies[key] = strategy

        self.logger.info(f"策略已注册: {key}")

    async def start_strategy(self, strategy_name: str, symbol: str):
        """启动策略"""
        key = f"{strategy_name}_{symbol}"
        if key not in self.strategies:
            raise StrategyError(f"策略不存在: {key}")

        strategy = self.strategies[key]
        if not strategy.is_running():
            await strategy.initialize()
            self.active_strategies.add(key)
            self.logger.info(f"策略已启动: {key}")

    async def stop_strategy(self, strategy_name: str, symbol: str):
        """停止策略"""
        key = f"{strategy_name}_{symbol}"
        if key in self.strategies:
            strategy = self.strategies[key]
            await strategy.stop()
            self.active_strategies.discard(key)
            self.logger.info(f"策略已停止: {key}")

    async def pause_strategy(self, strategy_name: str, symbol: str):
        """暂停策略"""
        key = f"{strategy_name}_{symbol}"
        if key in self.strategies:
            strategy = self.strategies[key]
            await strategy.pause()
            self.logger.info(f"策略已暂停: {key}")

    async def resume_strategy(self, strategy_name: str, symbol: str):
        """恢复策略"""
        key = f"{strategy_name}_{symbol}"
        if key in self.strategies:
            strategy = self.strategies[key]
            await strategy.resume()
            self.logger.info(f"策略已恢复: {key}")

    async def get_strategy_status(self, strategy_name: str, symbol: str) -> Dict[str, Any]:
        """获取策略状态"""
        key = f"{strategy_name}_{symbol}"
        if key not in self.strategies:
            return {'error': 'Strategy not found'}

        strategy = self.strategies[key]
        return strategy.get_status_info()

    async def get_all_strategies_status(self) -> Dict[str, Any]:
        """获取所有策略状态"""
        status = {}
        for key, strategy in self.strategies.items():
            status[key] = strategy.get_status_info()
        return status

    async def cleanup_all(self):
        """清理所有策略"""
        for key, strategy in self.strategies.items():
            try:
                await strategy.cleanup()
            except Exception as e:
                self.logger.error(f"清理策略失败 {key}: {e}")

        self.strategies.clear()
        self.active_strategies.clear()
        self.logger.info("所有策略已清理")


# 全局策略管理器实例
_strategy_manager = None

def get_strategy_manager() -> StrategyManager:
    """获取全局策略管理器实例"""
    global _strategy_manager
    if _strategy_manager is None:
        _strategy_manager = StrategyManager()
    return _strategy_manager

def init_strategy_manager() -> StrategyManager:
    """初始化策略管理器"""
    global _strategy_manager
    _strategy_manager = StrategyManager()
    return _strategy_manager
